<?php
/**
 * @Author: rocky
 * @Copyright: 广州拓冠科技 <http://my8m.com>
 * Date: 2019/8/29
 * Time: 11:50
 */


namespace app\shop\service;


use app\api\service\WechatService;
use app\common\facade\Token;
use app\common\model\Account;
use app\common\tools\Redis;
use app\shop\model\ShopCart;
use app\shop\model\ShopGoodsSpec;
use app\shop\model\ShopMemberAddress;
use app\shop\model\ShopOrder;
use app\shop\model\ShopOrderGoods;
use app\shop\model\ShopSeckillActivity;
use app\shop\model\ShopServiceAddress;
use app\shop\model\ShopSpell;
use app\shop\model\ShopSpellGood;
use library\tools\Data;
use think\Db;
use think\Exception;

class Order
{
    //拼团id
    static $pt_id = 0;
    /**
     * 确认订单
     * @Author: rocky
     * 2019/9/30 17:01
     * @param $post 提交校验数据
     * @return array
     */
    public static function confim($post)
    {
        $msg = false;
        $data = [];
        Db::startTrans();
        try {
            switch ($post['type']) {
                // 购物车
                case 1:
                    $carts = ShopCart::uid()->whereIn('id', $post['car_ids'])->with(['goods', 'spec' => function ($q) {
                        $q->lock(true);
                    }])->select();
                    if ($carts->isEmpty()) {
                        $msg = '您的购物车是空的';
                    }
                    foreach ($carts as $cart) {
                        //判断商品状态
                        if ($cart['goods']['status'] != 1) {
                            $msg = $cart['goods']['title'] . ' - 商品不存在或已下架';
                        }
                        //判断库存量
                        $stock = $cart['spec']['stock'] - $cart['spec']['sale'];
                        if ($stock < $cart['num']) {
                            $msg = $cart['goods']['title'] . ' - 商品库存量不足';
                        }
                        $data[] = [
                            'price_express' => $cart['goods']['price_express'],
                            'good_id' => $cart['goods']['id'],
                            'spec_id' => $cart['spec_id'],
                            'logo' => $cart['goods']['logo'],
                            'title' => $cart['goods']['title'],
                            'spec' => $cart['spec']['spec_name'],
                            'price' => $cart['spec']['price'],
                            'img' => $cart['spec']['thumb'],
                            'num' => $cart['num'],
                        ];
                    }
                    break;
                //商品详情;
                case 2:
                    $spec = ShopGoodsSpec::lock(true)->get($post['spec_id'], ['goods']);
                    if (!$spec) {
                        $msg = '此规格不存在';
                    }
                    //判断秒杀
                    if ($post['order_type'] == 3) {
                        $seckillActivity = ShopSeckillActivity::whereBetweenTimeField('start_time', 'end_time')->find($post['seckill_id']);
                        if (!$seckillActivity) {
                            $msg = '此商品不在秒杀时间段';
                        }
                        $price = $spec['seckill_price'];
                        //判断拼团
                    } elseif ($post['order_type'] == 4) {
                        $spellGood = ShopSpellGood::where('good_id', $spec['goods']['id'])->find();
                        if (!$spellGood) {
                            $msg = '此商品不是拼团商品';
                        }
                        if ($post['pt_id']) {
                            self::$pt_id = $post['pt_id'];
                            $shopSpell = ShopSpell::where('status', 1)->find($post['pt_id']);
                            if ($shopSpell) {
                                $order = ShopOrder::uid()->where('status', '>', 1)->where('pt_id', $post['pt_id'])->find();
                                if ($order) {
                                    $msg = '您已经参加了拼团';
                                }
                            } else {
                                $msg = '不存在的拼团或拼团已结束完成';
                            }
                        } else {
                            $spell = ShopSpell::create([
                                'good_id' => $spec['goods']['id'],
                                'num' => $spec['goods']['sepll_num'],
                                'uid'=>Token::id(),
                                'join_num' => 1,
                                'start_time' => date('Y-m-d H:i:s'),
                                'end_time' => date('Y-m-d H:i:s', time() + 3600 * sysconf('spell_cancel_time')),
                            ]);
                            self::$pt_id = $spell->id;
                        }
                        $price = $spec['spell_price'];
                    } else {
                        $price = $spec['price'];
                    }
                    //判断商品状态
                    if ($spec['goods']['status'] != 1) {
                        $msg = $spec['goods']['title'] . ' - 商品不存在或已下架';
                    }
                    //判断库存量
                    $stock = $spec['stock'] - $spec['sale'];
                    if ($stock < $post['num']) {
                        $msg = $spec['goods']['title'] . ' - 商品库存量不足';
                    }
                    $data[] = [
                        'price_express' => $spec['goods']['price_express'],
                        'good_id' => $spec['goods']['id'],
                        'spec_id' => $spec['id'],
                        'logo' => $spec['goods']['logo'],
                        'title' => $spec['goods']['title'],
                        'spec' => $spec['spec_name'],
                        'price' => $price,
                        'img' => $spec['thumb'],
                        'num' => $post['num'],
                    ];
                    break;
            }
            if ($msg) {
                Db::rollback();
            } else {
                Db::commit();
            }
        } catch (Exception $e) {
            Db::rollback();

        }
        return [$msg, $data];
    }

    /**
     * 下单
     * @Author: rocky
     * 2019/9/30 17:41
     * @param $post 提交校验数据
     * @return array|mixed|string
     * @throws \Exception
     */
    public static function place($post)
    {
        list($msg, $datas) = self::confim($post);
        if ($msg) {
            return $msg;
        } else {
            //获取地址
            if ($post['express_type'] == 1) {
                $address = ShopMemberAddress::uid()->find($post['address_id']);
                if (!$address) {
                    return '收货地址不存在';
                }
            } else {
                $address = ShopServiceAddress::find($post['address_id']);
                if (!$address) {
                    return '自提地址不存在';
                }
            }
            $uid = Token::id();
            //秒杀限量判断
            if ($post['order_type'] == 3) {
                $seckill = ShopSeckillActivity::find($post['seckill_id']);
                $redis = Redis::getRedis();
                $buyReidsKey = "seckill_buy_{$post['seckill_id']}";
                $seckill_num = $redis->hGet($buyReidsKey, "{$uid}_{$datas[0]['good_id']}");
                $buy_num = $seckill_num+$datas[0]['num'];
                if($buy_num > $seckill['user_shop_num']){
                    return '超出限购量';
                }
                $redis->hSet($buyReidsKey, "{$uid}_{$datas[0]['good_id']}",$buy_num);
            }
            $order_sn = Data::uniqidDateCode();
            $price_express = 0;
            $total_price = 0;
            $goods_price = 0;
            //统计金额
            foreach ($datas as $data) {

                $goods_price += $data['price'] * $data['num'];
                $total_price += $goods_price + $data['price_express'];
                $price_express += $data['price_express'];
            }
            //商品标题
            $title = $datas[0]['title'];
            if (count($datas) > 1) {
                $title .= '等多件商品';
            }

            //订单数据组装
            $orderData = [
                'title' => $title,
                'uid' => Token::id(),
                'express_type' => $post['express_type'],
                'order_no' => $order_sn,
                'freight_price' => $price_express,
                'goods_price' => $goods_price,
                'total_price' => $total_price,
                'pay_type' => $post['pay_type'],
                'address_info' => json_encode($address, JSON_UNESCAPED_UNICODE),
                'desc' => $post['desc'],
            ];
            Db::startTrans();
            try {
                //删除购物车
                if ($post['type'] == 1) {
                    ShopCart::uid()->whereIn('id', $post['car_ids'])->delete();
                }
                $order = ShopOrder::create($orderData);
                $orderGoods = [];
                $specUpdateData = [];
                foreach ($datas as $data) {
                    //销量
                    $specUpdateData[] = [
                        'id' => $data['spec_id'],
                        'sale' => Db::raw("sale+{$data['num']}"),
                    ];
                    //快照组装
                    $orderGoods[] = [
                        'order_id' => $order['id'],
                        'good_id' => $data['good_id'],
                        'spec_id' => $data['spec_id'],
                        'good_title' => $data['title'],
                        'good_logo' => $data['logo'],
                        'spec_name' => $data['spec'],
                        'spec_img' => $data['img'],
                        'price' => $data['price'],
                        'num' => $data['num'],
                    ];
                }
                (new ShopGoodsSpec())->saveAll($specUpdateData);
                (new ShopOrderGoods)->saveAll($orderGoods);
                Db::commit();
                return [
                    'order_id' => $order['id'],
                    'total_price' => $total_price,
                ];
            } catch (Exception $e) {
                //秒杀下单失败，还原redis限购量
                if ($post['order_type'] == 3) {
                    $redis = Redis::getRedis();
                    $buyReidsKey = "seckill_buy_{$post['seckill_id']}";
                    $seckill_num = $redis->hGet($buyReidsKey, "{$uid}_{$datas[0]['good_id']}");
                    $buy_num = $seckill_num-$datas[0]['num'];
                    $redis->hSet($buyReidsKey, "{$uid}_{$datas[0]['good_id']}",$buy_num);
                }
                Db::rollback();
                return $e->getMessage();
            }
        }
    }

    /**
     * 拼团失败
     * @auth true
     * @menu true
     * @Author: rocky
     * 2019/12/13 10:54
     * @return bool
     */
    public static function sepllFail()
    {
        $pt_ids = ShopSpell::where('status', 1)->whereTime('end_time', '<=', time())->column('id');
        foreach ($pt_ids as $pt_id) {
            //设置拼团失败
            ShopSpell::where('id', $pt_id)->setField('status', 3);
            $orders = ShopOrder::where('pt_id', $pt_id)->where('is_pay', 1)->select();
            foreach ($orders as $order) {
                Db::startTrans();
                try {
                    //微信
                    if ($order['pay_type'] == 1) {
                        $res = WechatService::refund($order['transaction_id'], $order['order_no'], $order['total_price'], $order['pay_price']);
                        if ($res) {
                            Account::record($order['pay_price'],$order['uid'],"拼团失败 - 订单[{$order['title']}]",2,"退款至微信钱包 - 订单号：{$order['order_no']}");
                        }
                        //钱包
                    } elseif ($order['pay_type'] == 3) {
                        Account::recordMoney($order['pay_price'],$order['uid'],"钱包支付 - 订单[{$order['title']}]",2,"退款至钱包 - 订单号：{$order['order_no']}");
                    }

                    $order->status = -1;
                    $order->save();
                    Db::commit();
                } catch (\Exception $e) {
                    Db::rollback();
                }
            }
        }
        return true;
    }

    /**
     * 取消订单还原库存
     * @auth true
     * @menu true
     * @Author: rocky
     * 2019/12/13 10:54
     * @return bool
     */
    public static function cancel()
    {
        $orders = ShopOrder::where('status', 1)->whereTime('create_at', '<=', time() - sysconf('order_cancel_time') * 60 * 60)->select();
        foreach ($orders as $order) {
            Db::startTrans();
            try {
                //关闭订单
                $order->status = -1;
                $order->save();
                //2.将商品销量减少
                $orderList = ShopOrderGoods::where('order_id', $order['id'])->select();
                $specDataArr = [];
                foreach ($orderList as $key => $value) {
                    array_push($specDataArr, [
                        'id' => $value['spec_id'],
                        'sale' => Db::raw("sale-{$value['num']}"),
                    ]);
                }
                (new ShopGoodsSpec())->saveAll($specDataArr);
                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
            }
        }
        return true;
    }

    /**
     * 删除关闭订单
     * @auth true
     * @menu true
     * @Author: rocky
     * 2019/12/13 10:56
     * @return int
     */
    public static function del()
    {
        return ShopOrder::where('status', -1)->whereTime('create_at', '<=', time() - sysconf('order_cancel_del_time') * 60 * 60)->setField('is_deleted', 1);
    }

    /**
     * 确认收货
     * @auth true
     * @menu true
     * @Author: rocky
     * 2019/12/13 10:56
     * @return int
     */
    public static function confirm()
    {
        return ShopOrder::where('status', 3)->whereTime('delivery_time', '<=', time() - sysconf('order_confirm_time') * 60 * 60 * 24)->setField('status', 4);
    }
}